
#include "Target.h"

Target::Target(BScene* scene)
{
	_scene = scene;
}
Target::Target(BObject* object, BScene* scene)
{
	_scene = scene;
	if (BGroup* group = dynamic_cast<BGroup*>(object))
		insertGroup(group);
	else if (BNode* node = dynamic_cast<BNode*>(object))
		insertNode(node);
	else if (BShape* shape = dynamic_cast<BShape*>(object))
		insertShape(shape);
}
Target::Target(BGroup* group, BScene* scene)
{
	_scene = scene;
	insertGroup(group);
}
Target::Target(BNode* node, BScene* scene)
{
	_scene = scene;
	insertNode(node);
}
Target::Target(BShape* shape, BScene* scene)
{
	_scene = scene;
	insertShape(shape);
}
Target::Target(const Target& other)
{
	_dirty = other._dirty;
	_space = other._space;
	_scene = other._scene;
	for (int i = 0; i < other._groups.size(); i++)
		insertGroup(other._groups[i]);
	for (int i = 0; i < other._nodes.size(); i++)
		insertNode(other._nodes[i]);
	for (int i = 0; i < other._shapes.size(); i++)
		insertShape(other._shapes[i]);
}
Target::~Target()
{
	clear();
}

bool Target::empty() const
{
	return _groups.empty() && _nodes.empty() && _shapes.empty() && _constraints.empty();
}
const BSpace& Target::space() const
{
	if (_dirty)
	{
		_space.reset();
		if (BShape* first = _shapes.first())
		{
			if (_space.empty())
				_space = first->space();
			else
				_space.expand(first->space());
			for (int i = 1; i < _shapes.size(); i++)
			{
				_space.expand(_shapes[i]->space());
			}
		}
		else if (BNode* first = _nodes.first())
		{
			if (_space.empty())
				_space = first->space();
			else
				_space.expand(first->space());
			for (int i = 1; i < _nodes.size(); i++)
			{
				_space.expand(_nodes[i]->space());
			}
		}
		else if (BGroup* first = _groups.first())
		{
			if (_space.empty())
				_space = first->space();
			else
				_space.expand(first->space());
			for (int i = 1; i < _groups.size(); i++)
			{
				_space.expand(_groups[i]->space());
			}
		}
		_dirty = false;
	}
	return _space;
}

BScene* Target::scene()
{
	return _scene;
}
const BScene* Target::scene() const
{
	return _scene;
}

void Target::insertGroup(BGroup* group)
{
	if (group && _groups.append(group))
	{
		connect(group, Signal_Dirty, &Target::slotGroupDirty);
		_dirty = true;
		this->emit(Signal_Dirty);
	}
}
void Target::removeGroup(BGroup* group)
{
	if (_groups.remove(group))
	{
		disconnect(group, Signal_Dirty);
		_dirty = true;
		this->emit(Signal_Dirty);
	}
}
bool Target::containGroup(BGroup* group) const
{
	return _groups.contain(group);
}
void Target::clearGroups()
{
	for (int i = 0; i < _groups.size(); i++)
	{
		BGroup* group = _groups[i];
		disconnect(group);
	}
	_groups.clear();
	_dirty = true;
	this->emit(Signal_Dirty);
}

int Target::groupCount() const
{
	return _groups.size();
}
BGroup* Target::group(int index) const
{
	return _groups(index);
}
const BGroupHolderArray& Target::groups() const
{
	return _groups;
}

void Target::insertNode(BNode* node)
{
	if (node && _nodes.append(node))
	{
		connect(node, Signal_Dirty, &Target::slotNodeDirty);
		connect(node, Signal_Transformed, &Target::slotNodeTransformed);
		_dirty = true;
		this->emit(Signal_Dirty);
	}
}
void Target::removeNode(BNode* node)
{
	if (_nodes.contain(node))
	{
		disconnect(node);
		_nodes.remove(node);
		_dirty = true;
		this->emit(Signal_Dirty);
	}
}
bool Target::containNode(BNode* node) const
{
	return _nodes.contain(node);
}
void Target::clearNodes()
{
	for (int i = 0; i < _nodes.size(); i++)
	{
		BNode* node = _nodes[i];
		disconnect(node);
	}
	_nodes.clear();
	_dirty = true;
	this->emit(Signal_Dirty);
}

int Target::nodeCount() const
{
	return _nodes.size();
}
BNode* Target::node(int index) const
{
	return _nodes.at(index);
}
const BNodeHolderArray& Target::nodes() const
{
	return _nodes;
}

void Target::insertShape(BShape* shape)
{
	if (shape && _shapes.append(shape))
	{
		connect(shape, Signal_Dirty, &Target::slotShapeDirty);
		connect(shape, Signal_Transformed, &Target::slotShapeTransformed);
		_dirty = true;
		this->emit(Signal_Dirty);
	}
}
void Target::removeShape(BShape* shape)
{
	if (_shapes.remove(shape))
	{
		disconnect(shape);
		_shapes.remove(shape);
		_dirty = true;
		this->emit(Signal_Dirty);
	}
}
bool Target::containShape(BShape* shape) const
{
	return _shapes.contain(shape);
}
void Target::clearShapes()
{
	for (int i = 0; i < _shapes.size(); i++)
	{
		BShape* shape = _shapes[i];
		disconnect(shape);
	}
	_shapes.clear();
	_dirty = true;
	this->emit(Signal_Dirty);
}

int Target::shapeCount() const
{
	return _shapes.size();
}
BShape* Target::shape(int index) const
{
	return _shapes(index);
}
const BShapeHolderArray& Target::shapes() const
{
	return _shapes;
}

void Target::insertConstraint(BConstraint* constraint)
{
	if (constraint && _constraints.append(constraint))
	{
		this->emit(Signal_Dirty);
	}
}
void Target::removeConstraint(BConstraint* constraint)
{
	_constraints.remove(constraint);
}
bool Target::containConstraint(BConstraint* constraint) const
{
	return _constraints.contain(constraint);
}
void Target::clearConstraints()
{
	_constraints.clear();
}

int Target::constraintCount() const
{
	return _constraints.size();
}
BConstraint* Target::constraint(int index) const
{
	return _constraints(index);
}
const BConstraintHolderArray& Target::constraints() const
{
	return _constraints;
}

BNode* Target::findNode(BNode* node) const
{
	if (_nodes.contain(node))
		return node;
	return 0;
}
bool Target::contain(BObject* object) const
{
	for (int i = 0; i < _nodes.size(); i++)
	{
		if (_nodes[i] == object)
			return true;
	}
	for (int i = 0; i < _shapes.size(); i++)
	{
		if (_shapes[i] == object)
			return true;
	}
	for (int i = 0; i < _groups.size(); i++)
	{
		if (_groups[i] == object)
			return true;
	}
	return false;
}
bool Target::matchPickItem(BPickItem* item)
{
	if (!item)
		return 0;
	return 0;
}

void Target::clear()
{
	_dirty = false;
	_space.reset();
	clearNodes();
	clearShapes();
	clearGroups();
}

BObject* Target::object() const
{
	if (_shapes.size())
	{
		if (_shapes.size() == 1)
			return _shapes[0];
		return 0;
	}
	if (_nodes.size())
	{
		if (_nodes.size() == 1)
			return _nodes[0];
		return 0;
	}
	if (_groups.size())
	{
		if (_groups.size() == 1)
			return _groups[0];
		return 0;
	}
	return _scene;
}
BShape* Target::shape() const
{
	if (_shapes.size() == 1)
		return _shapes[0];
	return 0;
}
BNode* Target::node() const
{
	if (_nodes.size() == 1)
		return _nodes[0];
	return 0;
}
BGroup* Target::group() const
{
	if (_groups.size() == 1)
		return _groups[0];
	return 0;
}

bool Target::operator == (const BNode* node) const
{
	return _nodes.size() == 1 && _nodes[0] == node;
}
bool Target::operator == (const BShape* shape) const
{
	return _nodes.empty() && _shapes.size() == 1 && _shapes[0] == shape;
}

void Target::slotShapeDirty(BShape* shape)
{
	_dirty = true;
	this->emit(Signal_Dirty);
}
void Target::slotShapeTransformed(BShape* shape)
{
	_dirty = true;
	this->emit(Signal_Dirty);
}

void Target::slotNodeDirty(BNode* node)
{
	_dirty = true;
	this->emit(Signal_Dirty);
}
void Target::slotNodeTransformed(BNode* node)
{
	_dirty = true;
	this->emit(Signal_Dirty);
}

void Target::slotGroupDirty(BGroup* group)
{
	if (_nodes.empty() && _shapes.empty())
	{
		_dirty = true;
		this->emit(Signal_Dirty);
	}
}
